Skip to content

Fixed bug in SMT option matching#5

Merged
strub merged 7 commits intoEasyCrypt:1.0from
alleystoughton:1.0
Feb 28, 2018
Merged

Fixed bug in SMT option matching#5
strub merged 7 commits intoEasyCrypt:1.0from
alleystoughton:1.0

Conversation

@alleystoughton
Copy link
Copy Markdown
Member

@alleystoughton alleystoughton commented Feb 28, 2018

The third stage of filtering in the definition of option_matching had
a bug, meaning that attempts to rely on it resulted in assertion failures.
But that last stage - disambiguating from right to left - was arguably
hard for users to predict, anyway. So, fixed the third stage, but
left it out of algorithm.

(If it's really desired, easy to put it back in, as now it'll
work. But do we really think users will understand why, e.g., [prover
x=1] means [prover maxlemmas=1] - because the x in maxlemmas comes
earlier when working backward as opposed to the x in maxprovers?)

This is how option disambiguation works: First filter-in those option
names having the letters of the abbreviation abv in the correct
order. Then work through the letters of abv in order, keeping
only those option names in which each successive letter appears
as early as possible

The elements of prover [...] have one of the following forms, where s
is a string:

s (add s to the use-only list)
+s (add include s to the include/exclude list)
-s (add exclude s to the include/exclude list)

The include/exclude list is ordered, so that later instructions can
supersede earlier ones. The use-only list was not ordered, but now
is. The relative order of the use-only and include/exclude lists
is irrelevant, so that, e.g., prover ["Z3" +"Alt-Ergo"] and prover
[+"Alt-Ergo" "Z3"] are equivalent.

The semantics is that the use-only list is first interpreted (if it's
empty, one starts with the current provers as the base), and only then
are the instructions of the include/exclude list applied to it, in
order.

There was already the special use-only instruction "ALL". Now, there is
also the use-only instruction "CLEAR", which clears the use-only list,
but may be superseded by the use-only instructions that follow.

Examples (assuming "Z3" and "Alt-Ergo" are only known provers):
prover []. (* a no-op *)
prover [+"Z3"]  (* adds just "Z3" to whatever current provers are *)
prover [-"Z3"]  (* removes just "Z3" from whatever current provers are *)
prover ["ALL"]  (* results in "Z3", "Alt-Ergo" *)
prover ["CLEAR"]  (* results in nothing *)
prover ["CLEAR" +"Z3"]  (* results in just "Z3" *)
prover [+"Z3" "CLEAR"]  (* results in just "Z3" *)
prover ["CLEAR" "Z3"]  (* result in just "Z3" *)
prover ["Z3" "CLEAR"]  (* results in nothing *)
prover [-"Z3" "ALL"]  (* results in "Alt-Ergo" *)
prover [+"Z3" "ALL" -"Z3"]  (* results in "Alt-Ergo" *)
prover [-"Z3" "ALL" +"Z3"]  (* results in "Z3", "Alt-Ergo" *)
All use-only instructions must come first. There are two "universal"
use-only instructions: "" (all known provers), and "!" (no
provers). It is illegal to mix ""/"!" with prover names (no point
in doing so).

As before, if the use-only part is empty, it means the currently known
provers. The include/exclude instructions are processed in order,
acting on the result of the use-only part.

Examples (assuming "Z3" and "Alt-Ergo" are only known provers):

prover [].  (* no-op *)
prover [-"Z3"].  (* removes "Z3" from current provers *)
prover [+"Z3"].  (* adds "Z3" to current provers *)
prover [""].  (* results in "Z3", "Alt-Ergo" *)
prover ["!"].  (* results in no provers *)
prover ["Z3"].  (* results in "Z3" *)
prover ["Z3" "Alt-Ergo"].  (* results in "Z3", "Alt-Ergo" *)
prover ["!" +"Z3"].  (* results in "Z3" *)
prover ["" -"Z3"].  (* results in "Alt-Ergo" *)
The third stage of filtering in the definition of option_matching had
a bug, meaning that attempts to rely on it resulted in assertion failures.
But that last stage - disambiguating from right to left - was arguably
hard for users to predict, anyway. So, fixed the third stage, but
left it out of algorithm.

(If it's really desired, easy to put it back in, as now it'll
work. But do we really think users will understand why, e.g., [prover
x=1] means [prover maxlemmas=1] - because the x in maxlemmas comes
earlier when working backward as opposed to the x in maxprovers?)

This is how option disambiguation works: First filter-in those option
names having the letters of the abbreviation abv in the correct
order. Then work through the letters of abv in order, keeping
only those option names in which each successive letter appears
as early as possible
@strub strub merged commit 9867134 into EasyCrypt:1.0 Feb 28, 2018
strub added a commit that referenced this pull request Apr 30, 2026
…hange)

Splits the existing TcCtt resolution logic into three named local helpers — strat_tvar_via_tvtc, strat_abs_via_decl, strat_infer_by_carrier — corresponding to catalog modes #5, #6, and #1/#2 in doc/typeclasses-inference.md.

Behavior is identical: same dispatch order, same failures, same pickup of [Tvar a]/[Tconstr p] cases, same parking of univar carriers. The refactor exists so Phase 3 can drop a By-args strategy in without disturbing the existing logic.
strub added a commit that referenced this pull request May 1, 2026
Five related fixes that unblock multi-param TC inference:

1. UniEnv.tparams now derefs each tc_arg through Unify.close so the
   stored ax_tparams of a lemma carry resolved Tvars, not the stale
   Tunivars left over from typing-time opentvi calls. Without this,
   reusing a lemma whose tparams had constraints over earlier tparams
   left the constraint args as unbound Tunivars.

2. Tvar.subst_tc was a no-op — now it actually walks tc_args and
   substitutes through them. pf_check_tvi relied on this to
   instantiate constraints before infer.

3. TC class declarations (axioms + ops) thread ~tw_uni when calling
   Tuni.subst, matching the lemma path.

4. Unifier's `TcCtt` no-deps branch now parks on arg_deps when the
   carrier is concrete but its TC arg univars are still pending,
   instead of failing outright. Prevents premature failure when a TC
   op is type-checked before its arguments.

5. eq_tc compares TC arg types only, not their tcwitness components.
   The witnesses are determined by the (carrier, args) and may
   legitimately differ in shape (TCIUni vs TCIAbstract) while picking
   out the same TC at the structural level — comparing them
   prevented Mode #5 from matching a candidate whose type args
   matched but whose witnesses were typing-time stale.

Plus: `Tunivar↔Tunivar` union now merges the two sources' byunivar
entries onto the new representative so parked TC problems still fire
when the canonical univar is later bound.

Effects: tc/parametric.ec and tc/multi-param.ec now pass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants